package com.sumer.psychology.blog.infrastructure.persistence.mongo;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
import com.sumer.psychology.blog.domain.model.BlogAvailability;
import com.sumer.psychology.common.persistence.mongodb.AbstractMongoRepository;
import com.sumer.psychology.common.persistence.mongodb.MongoEventUtil;
import org.apache.commons.lang3.StringUtils;

import javax.inject.Inject;

/**
 * mongo的目录List
 * <p/>
 * Created by zhu on 14-10-12.
 */
public class MongoCategoryListRepository extends AbstractMongoRepository {
    private static final String DB_NAME = "sumer_category_list";
    private static final String CATEGORY_KEY = "categoryId.identity";

    @Inject
    private MongoBlogRepository mongoBlogRepository;

    /**
     * 增加category
     *
     * @param data json
     */
    public void add(String data) {
        DBObject category = initializeData(data, CATEGORY_KEY);
        String authorId = nestedValue(category, "author.identity");
        category.removeField("author");
        category.put("size", 0);

        db().getCollection(DB_NAME).update(
                new BasicDBObject("_id", authorId),
                new BasicDBObject("$push", new BasicDBObject("categories", category)),
                true, // upsert
                false);
    }

    /**
     * 修改category（重命名）
     *
     * @param data json
     */
    public void change(String data) {
        DBObject changedCategory = initializeData(data, CATEGORY_KEY);
        String categoryId = (String) changedCategory.get("_id");
        String changedName = (String) changedCategory.get("name");

        db().getCollection(DB_NAME).update(
                new BasicDBObject("categories._id", categoryId),
                new BasicDBObject("$set", new BasicDBObject("categories.$.name", changedName)));

    }

    /**
     * 删除category
     *
     * @param categoryId category id
     */
    public void removeCategory(String categoryId) {
        db().getCollection(DB_NAME).update(
                new BasicDBObject(),
                new BasicDBObject("$pull",
                        new BasicDBObject("categories", new BasicDBObject("_id", categoryId))));
    }

    /**
     * 增加一个blog
     *
     * @param data json
     */
    public void changeBlogSize(String data) {
        DBObject blog = MongoEventUtil.filterEventObject((DBObject) JSON.parse(data));
        String newCategoryId = (String) blog.get("categoryId");
        String blogId = nestedValue(blog, "blogId.identity");
        String authorId = nestedValue(blog, "author.identity");

        DBObject currentBlog = mongoBlogRepository.findOne(blogId);
        String oldCategoryId = (String) currentBlog.get("categoryId");
        if (StringUtils.isNotBlank(oldCategoryId)) {
            updateCategoryBlogSize(oldCategoryId, authorId, -1);
        }

        updateCategoryBlogSize(newCategoryId, authorId, 1);
    }

    /**
     * 增加一个blog
     *
     * @param data json
     */
    public void increaseBlogSize(String data) {
        DBObject blog = MongoEventUtil.filterEventObject((DBObject) JSON.parse(data));
        String categoryId = (String) blog.get("categoryId");
        String authorId = nestedValue(blog, "author.identity");

        updateCategoryBlogSize(categoryId, authorId, 1);
    }

    private void updateCategoryBlogSize(String categoryId, String authorId, int updateSize) {
        DBObject queryObject = new BasicDBObject()
                .append("_id", authorId)
                .append("categories._id", categoryId);

        db().getCollection(DB_NAME).update(
                queryObject,
                new BasicDBObject("$inc", new BasicDBObject("categories.$.size", updateSize)));
    }

    /**
     * 删除一个blog
     *
     * @param blogId blog id
     */
    public void removeBlog(String blogId) {
        recycleBlog(blogId, -1);
    }

    /**
     * 恢复一个blog
     *
     * @param blogId blog id
     */
    public void restoreBlog(String blogId) {
        recycleBlog(blogId, 1);
    }

    /*
     * blog回收站操作
     */
    private void recycleBlog(String blogId, int size) {
        DBObject blog = mongoBlogRepository.findOne(blogId, BlogAvailability.DEACTIVE);
        String categoryId = (String) blog.get("categoryId");

        if (StringUtils.isNotBlank(categoryId)) {
            String authorId = nestedValue(blog, "author.identity");
            DBObject queryObject = new BasicDBObject("_id", authorId)
                    .append("categories._id", categoryId);

            db().getCollection(DB_NAME).update(
                    queryObject,
                    new BasicDBObject("$inc", new BasicDBObject("categories.$.size", size)));
        }
    }

    @Override
    protected String dbName() {
        return DB_NAME;
    }

    public void setMongoBlogRepository(MongoBlogRepository mongoBlogRepository) {
        this.mongoBlogRepository = mongoBlogRepository;
    }
}
